﻿using AssemblyViewer.Model;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;

namespace AssemblyViewer.ViewModel
{
    class MainWindowViewModel : ViewModelBase
    {
        public string SpecficAssemblyName { get; set; }

        public ObservableCollection<AssemblyItem> SupportedAssemblies { get; set; }

        private AssemblyItem defaultAssemblyItem;
         
        public AssemblyItem DefaultAssemblyItem
        {
            get { return defaultAssemblyItem; }
            set
            {
                defaultAssemblyItem = value;
                base.OnPropertyChanged("DefaultAssemblyItem");
            }
        }

        public RelayCommand OpenCommand { get; set; }

        public RelayCommand AnalyseCommand { get; set; }

        public AssemblyDetailInfo ReferenceAssemblyInfo { get; set; }

        private BackgroundWorker myBackgroundWorker;

        public MainWindowViewModel()
        {
            this.SupportedAssemblies = new ObservableCollection<AssemblyItem>();

            this.myBackgroundWorker = new BackgroundWorker();
            this.myBackgroundWorker.WorkerReportsProgress = true;
            this.myBackgroundWorker.DoWork += DoWork;
            this.myBackgroundWorker.ProgressChanged += ProgressChanged;
            this.myBackgroundWorker.RunWorkerCompleted += RunWorkerCompleted;

            this.OpenCommand = new RelayCommand((input) =>
            {
                OpenFileDialog ofDialog = new OpenFileDialog();
                ofDialog.Multiselect = true;
                ofDialog.Filter = "Assembly File(*.DLL;*.EXE)|*.DLL;*.EXE";
                ofDialog.ShowDialog();

                string[] strFileNames = ofDialog.FileNames;

                if (null == strFileNames || 0 == strFileNames.Length)
                {
                    return;
                }

                RunLoadAssemblyWorker(strFileNames.Length, strFileNames);
            });
        }

        private void RunLoadAssemblyWorker(int fileCount, string[] fileList, bool clearOldData = false)
        {
            if (clearOldData)
            {
                SupportedAssemblies.Clear();
            }

            this.myBackgroundWorker.RunWorkerAsync(fileList);
        }

        private void DoWork(object sender, DoWorkEventArgs e)
        {
            if (e.Argument == null)
            {
                return;
            }

            string[] files = e.Argument as string[];

            foreach (var filePath in files)
            {
                LoadAssembly(filePath);
            }
        }

        private void LoadAssembly(string filePath)
        {
            try
            {
                AppendToSupportList(new AssemblyItem(filePath));
            }
            finally
            {
                this.myBackgroundWorker.ReportProgress(SupportedAssemblies.Count);
            }
        }

        void ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.ProgressPercentage == 1)
            {
                DefaultAssemblyItem = SupportedAssemblies.FirstOrDefault(); 
            }
        }


        private void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Result != null)
            {
                MessageBox.Show(e.Result.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            MessageBox.Show("加载完成！", "Information", MessageBoxButton.OK, MessageBoxImage.Information);
        }

        private void AppendToSupportList(AssemblyItem item)
        {
            App.Current.Dispatcher.Invoke(new Action<AssemblyItem>((assemblyItem) =>
            {
                SupportedAssemblies.Add(assemblyItem);
            }),item);
        }
    }
}
